<template>
  <view>
    <view class="player-bar" v-if="!hidetime">
      <view class="time">{{ formatSecondsToMMSS(currentTime) }}</view>
      <slider
        class="slider"
        :value="sliderValue"
        @change="handleSliderChange"
        activeColor="#FF7C00"
        backgroundColor="#fff"
        block-color="#ff9900"
        block-size="12"
        :show-value="false" />
      <view class="time">{{ formatSecondsToMMSS(duration) }}</view>
    </view>
    <view class="player-actions">
      <!-- 左边区域 -->
      <slot name="left" />
      <view :class="['play-btn', { center: !isLike }]" @click="handleBtnClick">
        <!-- 暂停 -->
        <image v-if="videoIsPlay" class="play-icon" src="https://cdn.xmxiaomai.com/isong_static/music/ending.png" />
        <!-- 播放 -->
        <image v-else class="play-icon" src="https://cdn.xmxiaomai.com/isong_static/music/start.png" />
      </view>
      <!-- 右边区域 -->
      <slot name="right" />
    </view>
  </view>
</template>

<script>
/**
 * Props itemsProps
 * @prop {Boolean} play - 是否播放，双向绑定，绑定时需使用.sync 如果为true 则播放，为false 则暂停
 * ... 其他api同文档 （https://uniapp.dcloud.io/api/media/audio-context?id=createinneraudiocontext）
 */
export default {
  name: 'md-audio',
  props: {
    // 是否播放或暂停
    play: {
      type: Boolean,
      default: false,
    },
    // 播放src
    src: {
      type: String,
    },
    autoplay: {
      type: Boolean,
      // default: false
    },
    hidetime: {
      type: Boolean,
      default: false
    },
    loop: {
      type: Boolean,
      // default: false
    },
    // #ifdef MP-WEIXIN || MP-BAIDU || MP-TOUTIAO || MP-LARK || MP-JD || MP-KUAISHOU
    obeyMuteSwitch: {
      type: Boolean,
      // default: true
    },
    // #endif
    // 初始化回调
    initAudio: {
      type: Function,
    },
    // 自定义组件标识
    index: {
      type: [String, Number],
    },
    isLike: {
      type: Boolean,
      default: true,
    },
  },
  data() {
    return {
      currentTime: 0,
      duration: 0,
      videoIsPlay: false,
      sliderValue: 0,
    };
  },
  watch: {
    play(n) {
      if (n) {
        !this.videoIsPlay && this.audioPlay();
      } else {
        this.videoIsPlay && this.audioPause();
      }
    },
    src() {
      this.audioDestroy();
      this.contextInit();
    },
  },
  created() {
    this.contextInit();
  },
  beforeUnmount() {
    this.audioDestroy();
  },
  methods: {
    /**
     * 将秒转换为 分:秒
     * @param {Number} seconds - 秒数
     */
    formatSecondsToMMSS(seconds) {
      const min = Math.floor(seconds / 60);
      const sec = Math.floor(seconds % 60);
      return `${min}:${sec < 10 ? '0' + sec : sec}`;
    },
    audioPlay() {
      this.innerAudioContext && this.innerAudioContext.play();
    },
    audioPause() {
      this.innerAudioContext && this.innerAudioContext.pause();
    },
    audioOnPlay() {
      this.videoIsPlay = true;
      this.$emit('update:play', true);
    },
    audioOnPause() {
      this.videoIsPlay = false;
      this.$emit('update:play', false);
    },
    audioDestroy() {
      this.innerAudioContext && this.innerAudioContext.destroy && this.innerAudioContext.destroy();
      this.audioPropInit();
    },
    audioControls() {
      if (this.videoIsPlay) {
        this.audioPause();
      } else {
        this.audioPlay();
      }
    },
    handleBtnClick() {
      this.audioControls();
      this.$emit('update:play', this.videoIsPlay);
    },
    // 进度条回调
    handleSliderChange(e) {
      const position = e.detail.value;
      // 当前slider进度（0~100）
      this.sliderValue = position;
      // 获取当前进度（s）
      const _currentTime = (position / 100) * (this.innerAudioContext?.duration || 0);
      this.innerAudioContext.seek(_currentTime);
      !this.videoIsPlay && this.handleBtnClick();
    },
    contextInit() {
      let that = this;
      that.$emit('update:play', false);
      if (!that.src) {
        if (process.env.NODE_ENV !== 'production') {
          console.warn(`[md-audio warn]: 'src' 为空`);
        }
        return;
      }
      let innerAudioContext = uni.createInnerAudioContext();
      innerAudioContext.autoplay = that.autoplay;
      innerAudioContext.loop = that.loop;
      // #ifdef MP-WEIXIN || MP-BAIDU || MP-TOUTIAO || MP-LARK || MP-JD || MP-KUAISHOU
      if (typeof that.obeyMuteSwitch === 'boolean') {
        innerAudioContext.obeyMuteSwitch = that.obeyMuteSwitch;
      }
      // #endif
      innerAudioContext.onPlay((...arg) => {
        // 获取音乐时长
        that.duration = innerAudioContext?.duration || 0;
        that.audioOnPlay();
        that.$emit('onPlay', ...arg);
      });
      innerAudioContext.onPause((...arg) => {
        that.audioOnPause();
        that.$emit('onPause', ...arg);
      });
      innerAudioContext.onEnded((...arg) => {
        that.audioOnPause();
        that.$emit('onEnded', ...arg);
      });
      innerAudioContext.onTimeUpdate((...arg) => {
        // 获取音乐当前进度
        that.currentTime = innerAudioContext.currentTime;
        // 进度条处理
        that.sliderValue = (innerAudioContext.currentTime / (innerAudioContext?.duration || 0)) * 100;
        that.$emit('onTimeUpdate', ...arg);
      });
      innerAudioContext.onError((...arg) => {
        that.$emit('onError', ...arg);
      });
      innerAudioContext.src = that.src;
      if (that.initAudio) {
        that.initAudio(innerAudioContext, { src: that.src, index: that.index });
      }
      this.duration = innerAudioContext?.duration || 0;
      that.innerAudioContext = innerAudioContext;
    },
    audioPropInit() {
      this.currentTime = 0;
      this.duration = 0;
      this.videoIsPlay = false;
    },
  },
};
</script>

<style lang="scss" scoped>
.bottom-player-bar {
  position: fixed;
  padding: 0 59rpx;
  bottom: 68rpx;
  width: calc(100% - 118rpx);
}
.player-bar {
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 32rpx 0 0 0;
}
.time {
  font-size: 24rpx;
  color: #bbb;
  width: 80rpx;
  text-align: center;
}
.slider {
  flex: 1;
  margin: 0 20rpx;
}
.player-actions {
  // position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-top: 24rpx;
}
.action {
  font-size: 48rpx;
  color: #fff;
  width: 40rpx;
  height: 40rpx;
}
.play-btn {
  margin: auto;
  width: 100rpx;
  height: 100rpx;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0 48rpx;
  box-shadow: 0 4rpx 24rpx 0 #111;
  &.center {
    position: relative;
    left: 0;
    right: 0;
    margin: auto;
  }
}
.play-icon {
  width: 100rpx;
  height: 100rpx;
}
</style>
